package com.wkbb.basic.controller.manage;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.wkbb.basic.model.Family;
import com.wkbb.basic.model.Student;
import com.wkbb.basic.model.User;
import com.wkbb.basic.service.FamilyService;
import com.wkbb.basic.service.StudentService;
import com.wkbb.basic.service.UserOpenService;
import com.wkbb.basic.service.UserService;
import com.wkbb.basic.thread.BasicSetImportResultTask;
import com.wkbb.basic.thread.ChangeClassTask;
import com.wkbb.basic.thread.ImportStudentTask;
import com.wkbb.basic.vo.StudentChangeClassUserVo;
import com.wkbb.basic.vo.StudentChangeClassVo;
import com.wkbb.basic.vo.StudentManageEditVo;
import com.wkbb.common.base.BaseController;
import com.wkbb.common.constants.ErrorCode;
import com.wkbb.common.constants.RedisKeyConstant;
import com.wkbb.common.constants.VersionConstant;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.FamilyInfoDto;
import com.wkbb.common.dto.basic.StudentDetail;
import com.wkbb.common.dto.basic.StudentInfoDto;
import com.wkbb.common.dto.basic.UserDto;
import com.wkbb.common.enums.ChangeClassOperateTypeEnum;
import com.wkbb.common.enums.RoleTypeEnum;
import com.wkbb.common.enums.SysRoleTypeEnum;
import com.wkbb.common.enums.UserTypeEnum;
import com.wkbb.common.handler.JsonUtil;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.common.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static com.wkbb.common.constants.RedisKeyConstant.WKBB_BASIC_IMPORT_RESULT;

/**
 * @author dengjingyuan
 * @date 2019-07-04 10:32
 */
@RestController
@Api(description = "学生管理(后台管理)")
@RequestMapping("/basic/{apiVersion}/student/manage")
@Slf4j
public class StudentManageController extends BaseController {

    @Autowired
    private StudentService studentService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Autowired
    private FamilyService familyService;

    @Autowired
    private BasicSetImportResultTask basicSetImportResultTask;

    @Autowired
    private UserOpenService userOpenService;

    private static final Integer PAGE_SIZE = 200;
    private static final Integer MAX_IMPORT_NUM_OF_CLEAR_ADDRESS_BOOK = 50;//一次性导入学生数量超过这个值，就不再单个清理通讯录缓存


    @ApiOperation(value = "新增学生")
    @RequestMapping(value = "/addStudent", method = RequestMethod.POST)
    public ResultDTO addStudent(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @RequestBody StudentManageEditVo studentManageEditVo) {
        log.info("***********StudentManageController.addStudent******...apiVersion:{},Student:{}", apiVersion, studentManageEditVo);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        String redisKey = RedisKeyConstant.WKBB_SYSTEM + "addStudent:" +"userId:"+userDto.getId();

        String addStudentRedisKey = RedisKeyConstant.WKBB_SYSTEM + "addStudent:" + "redis:" +"userId:"+userDto.getId();
        log.info("\n防单个管理员重复提交............ 开始..准备开始获取分布式锁......addStudent,userId:{}" , userDto.getId());
        boolean lock = false;
        int retryCount = 0;
        while (!lock) {
            try {
                lock = redisTemplateUtil.tryLock(redisKey, userDto.getId().toString(), 20, TimeUnit.SECONDS);
                log.info("#################" + redisKey, "加锁 ", userDto.getId());

            } catch (Exception e) {
                log.info("#################加锁失败..等待锁过期 ：" + redisKey, userDto.getId());
                e.printStackTrace();
            }

            if (lock) {
                try {
                    //防重复数据提交并发判断
                    if(null!=redisTemplateUtil.get(addStudentRedisKey)){
                        redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                        return new ResultDTO<>(ErrorCode.SYSTEM_REPEAT);
                    }else{
                        //设置防重复用户redis
                        redisTemplateUtil.set(addStudentRedisKey, true, RedisKeyConstant.EXPIRATION_SECOND_1);
                    }
                } catch (Exception e) {
                    log.error("----------新增学生异常----------{}", e.getMessage());
                } finally {
                    log.info("#################" + redisKey, "开始释放锁 ", userDto.getId());
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    log.info("#################" + redisKey, "释放锁成功 ", userDto.getId());
                }

                try {
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                } catch (Exception e) {
                    log.info("#################释放锁失败..等待锁过期 ," + redisKey, "释放锁成功 ", userDto.getId().toString());
                    e.printStackTrace();
                }
            } else {
                try {
                    retryCount++;
                    if(retryCount>100){
                        log.info("加锁失败，重试超过100次，新增学生失败...userId:{}" ,  userDto.getId());
                        break;
                    }
                    log.info("等待100ms重试..." + redisKey, "释放锁成功 ", userDto.getId().toString());
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();
        if (checkData(studentInfoDto)) {
            return new ResultDTO(ErrorCode.PARAM_MISSING);
        }

        try {
        	
        	ErrorCode errorCode;
            //检查家长手机
           /*  errorCode = checkFamily(studentManageEditVo);
            if (errorCode != null) {
                return new ResultDTO(errorCode);
            }*/

            //检查是否已存在
            if (studentInfoDto.getUserId() != null && studentInfoDto.getUserId() != 0) {
                Map<String, Object> params = new HashMap<>(2);
                params.put("orgId", studentInfoDto.getOrgId());
                params.put("userId", studentInfoDto.getUserId());

                List<Student> exists = studentService.getListByMapParams(params);
                if (exists != null && !exists.isEmpty()) {
                    return new ResultDTO(ErrorCode.STUDENT_EXISTS);
                }
            }

            //检查卡号
           /* JSONArray jsonArray = new JSONArray();
            if (!StringUtils.isEmpty(studentInfoDto.getCardNo()) && !studentInfoDto.getCardNo().toString().contains("[]")) {
                jsonArray = JSON.parseArray(JSON.toJSONString(studentInfoDto.getCardNo()));
            }
            List<String> cardNoList = assembleCardNos(jsonArray, studentManageEditVo.getFamilyInfoList());
            //判断传入的是否重复
            long nextCount = cardNoList.stream().distinct().count();//经过去重之后的集合长度
            if (cardNoList.size() != nextCount) {
                return new ResultDTO(ErrorCode.CARDNO_HAS_REPEAT);
            }
            List<Long> userList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(studentManageEditVo.getFamilyInfoList())) {
                studentManageEditVo.getFamilyInfoList().forEach(e -> {
                    if (e.getUserId() != null) {
                        userList.add(e.getUserId());
                    }
                });
            }*/

            //判断卡号是否已经注册过
           /* for (String cardNo : cardNoList) {
                if (userService.checkCardNo(cardNo, studentInfoDto.getOrgId(), userList)) {
                    return new ResultDTO(ErrorCode.CARDNO_HAS_REGISTER);
                }
            }*/

            //检查学号
            errorCode = userService.checkMobileErrorCode(null, null, studentInfoDto.getStudentNo(), null,
                    RoleTypeEnum.STUDENT.getValue(), studentInfoDto.getOrgId(),studentInfoDto.getClassId());
            if (errorCode != null) {
                return new ResultDTO(errorCode);
            }

            studentService.insert(studentManageEditVo, userDto.getName(),true,true);
            return new ResultDTO<>(true);
        } catch (Exception e) {
            log.error("***********StudentManageController.addStudent******", e);
            return new ResultDTO<>(false);
        }
    }

    /**
     * 组装所有卡号
     *
     * @param jsonArray
     * @param familyInfoList
     * @return
     */
    private List<String> assembleCardNos(JSONArray jsonArray, List<FamilyInfoDto> familyInfoList) {

        List<String> cardNoList = new ArrayList<>();
        if (jsonArray != null && jsonArray.size() != 0) {
            for (Object o : jsonArray) {
                if (StringUtil.isNotEmpty(o.toString())) {
                    cardNoList.add(o.toString());
                }
            }
        }
        if (!CollectionUtils.isEmpty(familyInfoList)) {
            for (FamilyInfoDto familyInfoDto : familyInfoList) {
                if (StringUtil.isNotEmpty(familyInfoDto.getCardNo())) {
                    cardNoList.add(familyInfoDto.getCardNo());
                }
            }
        }

        return cardNoList;
    }

    /**
     * 检查学生管理视图数据
     * 幼儿园添加学生必填项: 学生姓名，性别，班级，家长手机号1，家长关系1
     *
     * @param studentInfoDto 学生管理视图数据
     * @return 是否未通过检测
     */
    private boolean checkData(StudentInfoDto studentInfoDto) {
        return studentInfoDto == null || studentInfoDto.getOrgId() == null || studentInfoDto.getOrgId() == 0
                || studentInfoDto.getGradeId() == null || studentInfoDto.getGradeId() == 0
                || studentInfoDto.getClassId() == null || studentInfoDto.getClassId() == 0
                || StringUtil.isNullOrBlank(studentInfoDto.getName())
                || StringUtil.isNullOrBlank(studentInfoDto.getSex());
    }

    /**
     * 检查家长信息
     *
     * @param studentManageEditVo 学生管理视图对象
     * @return 检测不通过，返回错误代码，
     * 检测通过，返回null
     */
    private ErrorCode checkFamily(StudentManageEditVo studentManageEditVo) throws Exception {
        List<FamilyInfoDto> familyInfoList = studentManageEditVo.getFamilyInfoList();
        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();
        if (familyInfoList != null && !familyInfoList.isEmpty()) {

            List<String> mobileStrs = new ArrayList<>();
            for (FamilyInfoDto familyInfoDto : familyInfoList) {
                if (familyInfoDto == null) {
                    continue;
                }

                //有家长没给手机号
                if (StringUtil.isNullOrBlank(familyInfoDto.getMobile())) {
                    return ErrorCode.PARAM_MISSING;
                }

                ErrorCode result = userService.checkMobileErrorCode(familyInfoDto.getMobile(), familyInfoDto.getCardNo(),
                        null, familyInfoDto.getUserId(), RoleTypeEnum.FAMILY.getValue(), studentInfoDto.getOrgId(),null);
                if (result != null) {
                    return result;
                }
                mobileStrs.add(familyInfoDto.getMobile());
            }
            //判断手机号是否重复
            if (mobileStrs.size() != mobileStrs.stream().distinct().count()) {
                return ErrorCode.MOBILE_HAS_REPEAT;
            }
        }
        return null;
    }

    @ApiOperation(value = "修改学生")
    @RequestMapping(value = "/updateStudent", method = RequestMethod.PUT)
    public ResultDTO updateStudent(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @RequestBody StudentManageEditVo studentManageEditVo) {
        log.info("***********StudentManageController.updateStudent******...apiVersion:{},Student:{}", apiVersion, studentManageEditVo);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();
        if (checkData(studentInfoDto) || studentInfoDto.getId() == null || studentInfoDto.getId() == 0
                || studentInfoDto.getUserId() == null || studentInfoDto.getUserId() == 0) {
            return new ResultDTO<>(ErrorCode.PARAM_MISSING);
        }

        try {
            //检查家长手机
            ErrorCode errorCode = checkFamily(studentManageEditVo);
            if (errorCode != null) {
                return new ResultDTO(errorCode);
            }

            //************************************************检查卡号开始***************************************
            //判断传入的卡号是否有重复
           /* JSONArray jsonArray = new JSONArray();
            if (!StringUtils.isEmpty(studentInfoDto.getCardNo()) && !studentInfoDto.getCardNo().toString().contains("[]")) {
                jsonArray = JSON.parseArray(JSON.toJSONString(studentInfoDto.getCardNo()));
            }
            List<FamilyInfoDto> familyInfos = studentManageEditVo.getFamilyInfoList();
            List<String> cardNoList = assembleCardNos(jsonArray, familyInfos);
            long nextCount = cardNoList.stream().distinct().count();//经过去重之后的集合长度
            if (cardNoList.size() != nextCount) {
                return new ResultDTO(ErrorCode.CARDNO_HAS_REPEAT);
            }

            //需要校验的卡号集合
            List<String> checkCardNoList = new ArrayList<>();
            //查询该学生及其家长已注册过的历史卡号,如果查询历史卡号为空，而现有卡号不为空，则需要校验
            JSONArray jsonArrayHis = new JSONArray();
            StudentManageEditVo studentManageEditVo1 = studentService.getStudentInfoWithFamilyListById(studentInfoDto.getId());
            if (studentManageEditVo1 != null && studentManageEditVo1.getStudentInfoDto() != null
                    && !StringUtils.isEmpty(studentManageEditVo1.getStudentInfoDto().getCardNo())
                    && !studentManageEditVo1.getStudentInfoDto().getCardNo().toString().contains("[]")) {
                jsonArrayHis = JSON.parseArray(JSON.toJSONString(studentManageEditVo1.getStudentInfoDto().getCardNo()));
            } else {
                checkCardNoList.addAll(assembleCardNos(jsonArray, null));
            }
            List<FamilyInfoDto> familyInfoListHis = studentManageEditVo1.getFamilyInfoList();

            for (FamilyInfoDto familyInfoDto : familyInfos) {
                for (FamilyInfoDto familyInfoHis : familyInfoListHis) {
                    if (familyInfoDto.getMobile().equals(familyInfoHis.getMobile()) && StringUtil.isEmpty(familyInfoHis.getCardNo())
                            && StringUtil.isNotEmpty(familyInfoDto.getCardNo())) {
                        checkCardNoList.add(familyInfoDto.getCardNo());
                    }
                }
            }

            //如果更改了卡号，则要校验更改的卡号不能重复，不能和数据库的卡号重复
            List<String> cardNoHisList = assembleCardNos(jsonArrayHis, familyInfoListHis);
            if (!CollectionUtils.isEmpty(cardNoList)) {
                for (String cardNo : cardNoList) {
                    if (!cardNoHisList.contains(cardNo)) {
                        checkCardNoList.add(cardNo);
                    }
                }
            }

            //判断历史数据是否重复
            if (!CollectionUtils.isEmpty(checkCardNoList)) {
                for (String cardNo : checkCardNoList) {
                    if (StringUtil.isNotEmpty(cardNo)) {
                        if (userService.checkCardNo(cardNo, studentInfoDto.getOrgId())) {
                            return new ResultDTO(ErrorCode.CARDNO_HAS_REGISTER);
                        }
                    }
                }
            }*/
            //******************************************************检查卡号结束***************************************************

            //检查学号
            errorCode = userService.checkMobileErrorCode(null, null, studentInfoDto.getStudentNo(), studentInfoDto.getUserId(),
                    RoleTypeEnum.STUDENT.getValue(), studentInfoDto.getOrgId(),studentInfoDto.getClassId());
            if (errorCode != null) {
                return new ResultDTO(errorCode);
            }

            List<FamilyInfoDto> familyInfoList = studentManageEditVo.getFamilyInfoList();
            if (familyInfoList != null && !familyInfoList.isEmpty()) {
                for (FamilyInfoDto familyInfoDto : familyInfoList) {
                    if (familyInfoDto == null || familyInfoDto.getUserId() == null) {
                        //如果用户ID为空，则根据手机号查询用户，如果存在，则补上用户ID
                        if (null == familyInfoDto.getUserId() && !StringUtils.isEmpty(familyInfoDto.getMobile())) {
                            User user = userService.getUserByMobile(familyInfoDto.getMobile());
                            if (null != user) {
                                familyInfoDto.setUserId(user.getId());
                            }
                        }
                        continue;
                    }
                    //TODO 后台暂不支持修改手机
                    familyInfoDto.setMobile(null);
                }
            }

            studentService.update(studentManageEditVo, userDto.getName(),true);
            return new ResultDTO<>(true);
        } catch (Exception e) {
            log.error("***********StudentManageController.updateStudent******", e);
            return new ResultDTO<>(false);
        }
    }


    @ApiOperation(value = "删除学生")
    @RequestMapping(value = "/deleteStudent", method = RequestMethod.DELETE)
    public ResultDTO deleteStudent(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "学生id", defaultValue = "29", required = true) @RequestParam(name = "id", required = true) List<Long> ids,
            @ApiParam(value = "是否提交(0:只是提示,1正常提交)", defaultValue = "0", required = true) @RequestParam(name = "type", required = true) Integer type
    ) {
        log.info("***********StudentManageController.deleteStudent******...apiVersion:{},Student:{}，type:{}", apiVersion, Arrays.toString(ids != null ? ids.toArray() : new Object[0]), type);
        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }
        try {
            return studentService.deleteStudent(ids, userDto.getName(), type);
        } catch (Exception e) {
            log.error("***********StudentManageController.deleteStudent******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "查询学生详情")
    @RequestMapping(value = "/getStudentInfoById", method = RequestMethod.GET)
    public ResultDTO<StudentManageEditVo> getStudentInfoById(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "学生表id", defaultValue = "29", required = true) @RequestParam(name = "id", required = true) Long id) {
        log.info("***********StudentManageController.getStudentInfoById******...apiVersion:{},Student:{}", apiVersion, id);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        try {
            return new ResultDTO<>(studentService.getStudentInfoWithFamilyListById(id));
        } catch (Exception e) {
            log.error("***********StudentManageController.getStudentInfoById******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "查询所有学生分页列表")
    @RequestMapping(value = "/getStudentPageList", method = RequestMethod.GET)
    public ResultDTO<PageInfo<StudentInfoDto>> getStudentPageList(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "类型 0校外 1校内", defaultValue = "1", required = false) @RequestParam(name = "type", required = false) Integer type,
            @ApiParam(value = "学生姓名", defaultValue = "", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(value = "家长手机", defaultValue = "", required = false) @RequestParam(name = "mobile", required = false) String mobile,
            @ApiParam(value = "性别", defaultValue = "", required = false) @RequestParam(name = "sex", required = false) String sex,
            @ApiParam(value = "页码", required = false) @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo,
            @ApiParam(value = "每页条数", required = false) @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        log.info("***********StudentManageController.getStudentPageList******...apiVersion:{},type:{},name:{},mobile:{},sex:{},pageNo:{},pageSize:{}", apiVersion,type
                , name, mobile, sex, pageNo, pageSize);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }
        try {
            HashMap<String, Object> params = new HashMap<>();
            params.put("orgId", type);
            if (!StringUtil.isNullOrBlank(name)) {
                params.put("name", name);
            }
            if (!StringUtil.isNullOrBlank(mobile)) {
                params.put("mobile", mobile);
            }
            if (!StringUtil.isNullOrBlank(sex)) {
                params.put("sex", sex);
            }
            return new ResultDTO<>(studentService.getStudentPageList(params, pageNo, pageSize));
        } catch (Exception e) {
            log.error("***********StudentManageController.getStudentPageList******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "查询学生分页列表")
    @RequestMapping(value = "/getStudentInfoPageList", method = RequestMethod.GET)
    public ResultDTO<PageInfo<StudentInfoDto>> getStudentInfoPageList(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "学校ID", defaultValue = "1", required = false) @RequestParam(name = "orgId", required = false) Long orgId,
            @ApiParam(value = "入学年份", required = false) @RequestParam(name = "enrollmentYear", required = false) Integer enrollmentYear,
            @ApiParam(value = "是否已报班", required = false) @RequestParam(name = "signUp", required = false) Boolean signUp,
            @ApiParam(value = "年级ID", defaultValue = "", required = false) @RequestParam(name = "gradeId", required = false) Long gradeId,
            @ApiParam(value = "班级ID", defaultValue = "", required = false) @RequestParam(name = "classId", required = false) Long classId,
            @ApiParam(value = "班级类型", defaultValue = "", required = false) @RequestParam(name = "classType", required = false) Integer classType,
            @ApiParam(value = "姓名", defaultValue = "", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(value = "手机", defaultValue = "", required = false) @RequestParam(name = "mobile", required = false) String mobile,
            @ApiParam(value = "家长手机", defaultValue = "", required = false) @RequestParam(name = "familyMobile", required = false) String familyMobile,
            @ApiParam(value = "学生卡号", defaultValue = "", required = false) @RequestParam(name = "cardNo", required = false) String cardNo,
            @ApiParam(value = "性别", defaultValue = "", required = false) @RequestParam(name = "sex", required = false) String sex,
            @ApiParam(value = "页码", required = false) @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo,
            @ApiParam(value = "每页条数", required = false) @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize) {


        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        try {
            HashMap<String, Object> params = new HashMap<>(3);
            params.put("orgId", orgId);
            params.put("gradeId", gradeId);
            params.put("classId", classId);
            params.put("classType", classType);
            params.put("enrollmentYear", enrollmentYear);
            if (signUp != null){
                params.put("signUp", signUp?1:0);
            }
            if (!StringUtil.isNullOrBlank(name)) {
                params.put("name", name);
            }
            if (!StringUtil.isNullOrBlank(mobile)) {
                params.put("mobile", mobile);
            }
            if (!StringUtil.isNullOrBlank(familyMobile)) {
                params.put("familyMobile", familyMobile);
            }
            if (!StringUtil.isNullOrBlank(sex)) {
                params.put("sex", sex);
            }
            if (!StringUtil.isNullOrBlank(cardNo)) {
                params.put("cardNo", cardNo);
            }
            log.info("***********StudentManageController.getStudentInfoPageList******...:{}", JsonUtil.objectToJson(params));
            return new ResultDTO<>(studentService.getStudentInfoPageList(params, pageNo, pageSize));
        } catch (Exception e) {
            log.error("***********StudentManageController.getStudentInfoPageList******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "根据班级查询学生分页列表")
    @RequestMapping(value = "getStudentInfoPageByClassId", method = RequestMethod.GET)
    public ResultDTO<PageInfo<StudentInfoDto>> getStudentInfoPageByClassId(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "学校ID", required = true, defaultValue = "1") @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "班级ID", required = true, defaultValue = "1") @RequestParam(name = "classId", required = true) Long classId,
            @ApiParam(value = "页码", required = false, defaultValue = "1") @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo,
            @ApiParam(value = "每页条数", required = false, defaultValue = "10") @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        log.info("***********StudentManageController.getStudentInfoPageByClassId******apiVersion:{},orgId:{},classId:{}", apiVersion, orgId, classId);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        try {
            if (orgId == 0 || classId == 0) {
                return new ResultDTO<>(ErrorCode.PARAM_MISSING);
            }

            Map<String, Object> params = new HashMap<>(2);
            params.put("orgId", orgId);
            params.put("classId", classId);

            return new ResultDTO<>(studentService.getStudentInfoPageByClassId(params, pageNo, pageSize));
        } catch (Exception e) {
            log.error("***********StudentManageController.getStudentInfoPageByClassId******", e);
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "导入学生和家长(导入结果要用getImportResult接口异步获取)")
    @PostMapping(value = "importExcelFile")
    public ResultDTO<Map<String,Object>> importExcelFile(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "学校ID", required = true, defaultValue = "2995") @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "(new:新学校导入 k12:k12学校导入)", required = true, defaultValue = "new") @RequestParam(name = "flag", required = true) String flag,
            @RequestParam("uploadFile") MultipartFile uploadFile) {
        UserDto userDto = getUserByLogin();

        log.info("----StudentManageController.importExcelFile开始----orgId={},flag={}", orgId, flag);

        if (userDto == null) {
            return new ResultDTO(ErrorCode.USER_NOT_EXIST);
        }

        if (SysRoleTypeEnum.SUPER_ADMIN.getValue() == getRoleTypeByUser(userDto)){
            orgId = 1L;
        }

        if (null == orgId || StringUtils.isEmpty(flag) || null == uploadFile) {
            return new ResultDTO(ErrorCode.PARAM_MISSING);
        }
        if (uploadFile.isEmpty()) {
            log.error("---StudentManageController.importExcelFile---文件不存在！");
            return new ResultDTO(ErrorCode.BUSINESS_DATA_WRONG);
        }
        //验证flag值,新学校只有19列数据,老学校有26列
        Integer columns = 0;
        if (!flag.equals("new") && !flag.equals("k12")) {
            return new ResultDTO(ErrorCode.PARAM_MISMATCH);
        }

        String redisKey = RedisKeyConstant.WKBB_SYSTEM + "importExcelFile:" + "orgId:" + orgId;
        String importExcelFileRedisKey = RedisKeyConstant.WKBB_SYSTEM + "importExcelFile:" +"redis:"+"orgId:" + orgId;

        log.info("\n防单个学校导入重复提交............ 开始..准备开始获取分布式锁......addStudent,userId:{}" , userDto.getId());
        boolean lock = false;
        int retryCount = 0;
        while (!lock) {
            try {
                lock = redisTemplateUtil.tryLock(redisKey, userDto.getId().toString(), 10, TimeUnit.SECONDS);
                log.info("#################" + redisKey, "加锁 ", userDto.getId());

            } catch (Exception e) {
                log.info("#################加锁失败..等待锁过期 ：" + redisKey, userDto.getId());
                e.printStackTrace();
            }

            if (lock) {
                InputStream in = null;
                try {
                    //防重复数据提交并发判断
                    if (null != redisTemplateUtil.get(importExcelFileRedisKey)) {
                        redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                        return new ResultDTO<>(ErrorCode.IMPORT_EXCEL_FILE);
                    } else {
                        //设置防重复用户redis
                        redisTemplateUtil.set(importExcelFileRedisKey, true, RedisKeyConstant.EXPIRATION_SECOND_10);
                    }

                    in = uploadFile.getInputStream();
                    List<Object> excelData = EasyExcel.read(in).sheet().doReadSync();
                    if (!CollectionUtils.isEmpty(excelData)) {
                        if (flag.equals("new") || flag.equals("k12")) {
                            Map mapTypes = (Map<String, Object>) excelData.get(1);
                            columns = mapTypes.size();
                            //获取List子集,从第二行开始获取,前面2行是标题行,只有第三行才是真正的数据行
                            excelData = excelData.subList(2, excelData.size());
                        }
                        List<Object[]> data = ObjectUtil.trans(excelData, columns);

                        //生成本地导入的唯一编号，用于异步获取导入结果
                        String orderNo = UUID.randomUUID().toString();
                        return preSaveOfImport(orderNo, userDto, orgId, data, flag, new Date());

//                        log.info("----StudentManageController.importExcelFile结束----orgId={},flag={}", orgId, flag);
                        //被强制取消，处理完所有线程后，再返回给用户界面提示异常
//                        return new ResultDTO<Object>(orderNo);
                    }

                } catch (RejectedExecutionException e) {
                    log.error("----已达到线程池最大等待队列---", e);
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    redisTemplateUtil.delete(importExcelFileRedisKey);
                    return new ResultDTO(ErrorCode.SYSTEM_THREAD_MAXQUEUE);
                }catch (ArrayIndexOutOfBoundsException e){
                    log.error("----导入模板异常,请检测---", e);
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    redisTemplateUtil.delete(importExcelFileRedisKey);
                    return new ResultDTO(ErrorCode.IMPORT_EXCEL_ERROR);
                }catch (Exception e) {
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    redisTemplateUtil.delete(importExcelFileRedisKey);
                    log.error("----StudentManageController.importExcelFile----", e);
                    return new ResultDTO(ErrorCode.SYSTEM_EXCEPTION);
                } finally {
                    log.info("#################" + redisKey, "开始释放锁 ", userDto.getId());
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    log.info("#################" + redisKey, "释放锁成功 ", userDto.getId());
                    if (null != in) {
                        try {
                            in.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

                try {
                    redisTemplateUtil.releaseLock(redisKey, userDto.getId().toString());
                    redisTemplateUtil.delete(importExcelFileRedisKey);
                } catch (Exception e) {
                    log.error("#################释放锁失败..等待锁过期 ," + redisKey, "释放锁成功 ", userDto.getId().toString());
                    e.printStackTrace();
                }
            } else {
                try {
                    retryCount++;
                    if(retryCount>20){
                        log.info("加锁失败，重试超过20次，导入学生和家长失败...orgId:{}" ,  orgId);
                        break;
                    }
                    log.info("等待500ms重试..." + redisKey, "释放锁成功 ", userDto.getId().toString());
                    Thread.sleep(500L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return new ResultDTO(ErrorCode.BUSINESS_DATA_WRONG);
    }

    @ApiOperation(value = "获取批量导入结果（结果被获取之后还会继续缓存一天）")
    @GetMapping(value = "getImportResult")
    public ResultDTO<Object> getImportResult(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "导入接口生成的唯一编号，由导入接口返回", required = true) @RequestParam(name = "orderNo", required = true) String orderNo
    ) {
        //数据存在redis里面去
        try {

            Object obj = redisTemplateUtil.get(WKBB_BASIC_IMPORT_RESULT + orderNo);
            Map<String, Object> returnMap = (Map<String, Object>) obj;
            redisTemplateUtil.set(WKBB_BASIC_IMPORT_RESULT + orderNo, returnMap, RedisKeyConstant.EXPIRATION_TIME_24_HOUR);//多缓存一天，以防万一还要用

            log.info("----批量导入学生,家长,从redis获取导入结果,key:{},value:{}", WKBB_BASIC_IMPORT_RESULT + orderNo, JSONObject.toJSONString(returnMap));
            return new ResultDTO<Object>(returnMap);

        } catch (Exception e) {
            log.error("----批量导入学生,家长,从redis获取导入结果 异常---", e);
            return new ResultDTO(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    /**
     * 多线程执行导入任务
     *
     * @param userDto
     * @param orgId
     * @param data
     * @param flag
     * @return
     * @throws Exception
     */
    private ResultDTO<Map<String,Object>> preSaveOfImport(String orderNo, UserDto userDto, Long orgId, List<Object[]> data, String flag,Date date) throws RejectedExecutionException,ArrayIndexOutOfBoundsException, Exception {
        Integer total = data.size();
        Integer pageSize = PAGE_SIZE;
        Integer pages = (total + pageSize - 1) / pageSize;

        /**
         * 遍历 data，找出不同学生相同家长的数据行，把这些数据放到同一个线程去运行，防止并发重复导入
         */
        List<Object[]> duplicatedData = new ArrayList<Object[]>();
        /*List<Integer> duplicatedRowNum = new ArrayList<>();*///data中出现重复数据的行号
        HashMap<String, Integer> map = new HashMap<String, Integer>();//手机号码为key，行号为value
        HashSet<Integer> hashSet = new HashSet<>();

        for (int index = 0; index < data.size(); index++) {

            int duplicatedRowIndex = 0;
            if (map.containsKey(data.get(index)[13].toString().trim())) {//familyMobile1
                duplicatedRowIndex = map.get(data.get(index)[13].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[13].toString().trim())) {
                map.put(data.get(index)[13].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[16].toString().trim())) {//familyMobile2
                duplicatedRowIndex = map.get(data.get(index)[16].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;

            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[16].toString().trim())) {
                map.put(data.get(index)[16].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[19].toString().trim())) {//familyMobile3
                duplicatedRowIndex = map.get(data.get(index)[19].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[19].toString().trim())) {
                map.put(data.get(index)[19].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[22].toString().trim())) {//familyMobile4
                duplicatedRowIndex = map.get(data.get(index)[22].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[22].toString().trim())) {
                map.put(data.get(index)[22].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[25].toString().trim())) {//familyMobile5
                duplicatedRowIndex = map.get(data.get(index)[25].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[25].toString().trim())) {
                map.put(data.get(index)[25].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[28].toString().trim())) {//familyMobile6
                duplicatedRowIndex = map.get(data.get(index)[28].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[28].toString().trim())) {
                map.put(data.get(index)[28].toString().trim(), index);
            }

            if (map.containsKey(data.get(index)[31].toString().trim())) {//familyMobile7
                duplicatedRowIndex = map.get(data.get(index)[31].toString().trim());

                duplicatedData.add(data.get(duplicatedRowIndex));
                duplicatedData.add(data.get(index));

                hashSet.add(duplicatedRowIndex);
                hashSet.add(index);
                continue;
            }

            if (StringUtil.isNotEmptyIgnoreBlank(data.get(index)[31].toString().trim())) {
                map.put(data.get(index)[31].toString().trim(), index);
            }
        }

        //缓存异步请求对象
//        List<FutureTask<ResultDTO<Map<String, Object>>>> futureTaskList = new ArrayList<>();

        //获取线程池
//        ExecutorService executorService = BasicThreadPoolUtil.getExecutorService(new BasicThreadPoolUtil(serviceConfig));
//        ExecutorService executorService = ThreadPoolUtil.getExecutorService();

        List<Integer> duplicatedRowNum = new ArrayList<>(hashSet);
        log.info("----------打印当前数据总数----------data:{}", data.size());
        log.info("----------打印重复数据总数----------duplicatedRowNum:{}", duplicatedRowNum.size());

        if (duplicatedRowNum.size() > 0) {
            Collections.sort(duplicatedRowNum, Collections.reverseOrder());
            //倒序删除重复的行

            duplicatedRowNum.forEach(duplicatedRow -> {
                data.remove(duplicatedRow.intValue());
            });

            //这里删除重复行之后，会导致行号跟原始excel里面的行号对不上，因为现在的错误提示不包含行号那么暂时不管这个问题。
        }

        FutureTask<ResultDTO<Map<String, Object>>> future;
        Integer currentRow = 0;
        Boolean isClearAddressBook = true;
        if(data.size() > MAX_IMPORT_NUM_OF_CLEAR_ADDRESS_BOOK || duplicatedRowNum.size() > MAX_IMPORT_NUM_OF_CLEAR_ADDRESS_BOOK){//同时导入超过50条数据，就不再一个个去清理用户通讯录缓存
            isClearAddressBook = false;
        }
        ResultDTO<Map<String,Object>> arrayResultDto = studentService.saveData(userDto,orgId,data,flag,currentRow,isClearAddressBook);
        return arrayResultDto;

//        if(data.size()>0){
//            for (int currentPage = 1; currentPage <= pages; currentPage++) {
//                List<Object[]> dataList = ListUtil.pager(currentPage, pageSize, data);
//                currentRow = (currentPage - 1) * pageSize + 4;
//                future = new FutureTask<ResultDTO<Map<String, Object>>>(new ImportStudentTask(studentService, userDto, orgId, dataList, flag, currentRow,isClearAddressBook));
//                executorService.execute(future);
//                //缓存到集合中集中获取
//                futureTaskList.add(future);
//            }
//        }
//
//        if (duplicatedRowNum.size() > 0) {//将重复的家长数据行单独一个线程去运行
//            //行号传了data.size()
//            future = new FutureTask<ResultDTO<Map<String, Object>>>(new ImportStudentTask(studentService, userDto, orgId, duplicatedData, flag, data.size(),isClearAddressBook));
//            executorService.execute(future);
//            //缓存到集合中集中获取
//            futureTaskList.add(future);
//        }


        //清理教职工和家长的通讯录缓存
//        if(!isClearAddressBook) {
//            userOpenService.deleteRedisAddressBookByOrgId(orgId, UserTypeEnum.FAMILY.getValue());
//        }

        //异步获取处理结果
//        setImportResult(orderNo, futureTaskList, orgId,date);
    }

    //处理异步线程结果,IM,XMPP
    public void setImportResult(String orderNo, List<FutureTask<ResultDTO<Map<String, Object>>>> futureTaskList, Long orgId,Date date) throws RejectedExecutionException {
        basicSetImportResultTask.setImportResult(orderNo,futureTaskList,orgId,date);
    }


    @ApiOperation(value = "查询线程池参数")
    @RequestMapping(value = "/getThreadPoolParam", method = RequestMethod.GET)
    public ResultDTO getThreadPoolParam(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion) {
        //BasicThreadPoolUtil basicThreadPoolUtil = new BasicThreadPoolUtil(serviceConfig);
        //获取线程池
        //ExecutorService executorService = BasicThreadPoolUtil.getExecutorService(basicThreadPoolUtil);
        ExecutorService executorService = ThreadPoolUtil.getExecutorService();
        HashMap<Object, Object> map = new HashMap<>();

        ThreadPoolExecutor tpe = ((ThreadPoolExecutor) executorService);
        int queueSize = tpe.getQueue().size();
        System.out.println("当前排队线程数：" + queueSize);
        map.put("currentQueueThreads：", queueSize);

        int activeCount = tpe.getActiveCount();
        System.out.println("当前活动线程数：" + activeCount);
        map.put("currentActiveThreads：", activeCount);

        long completedTaskCount = tpe.getCompletedTaskCount();
        System.out.println("执行完成线程数：" + completedTaskCount);
        map.put("currentFinishThreads：", completedTaskCount);

        long taskCount = tpe.getTaskCount();
        System.out.println("总线程数：" + taskCount);
        map.put("currentTotalThreads：", taskCount);

        map.put("minCoreThreads：", Runtime.getRuntime().availableProcessors()*10);
        map.put("maxThreads：", Runtime.getRuntime().availableProcessors()*10 * 8);
        map.put("maxWaitQueueThreads：", 2000);

        log.info("----------打印线程池配置----------executorService:{}",executorService);
        return new ResultDTO<>(map);
    }

    @ApiOperation(value = "导出学生列表excel")
    @RequestMapping(value = "/exportStudentInfoExcel", method = RequestMethod.GET)
    public ResultDTO exportStudentInfoExcel(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "学校ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "年级ID", required = false) @RequestParam(name = "gradeId", required = false) Long gradeId,
            @ApiParam(value = "班级ID", required = false) @RequestParam(name = "classId", required = false) Long classId,
            @ApiParam(value = "学生姓名", required = false) @RequestParam(name = "name", required = false) String name,
            @ApiParam(value = "家长手机", required = false) @RequestParam(name = "mobile", required = false) String mobile,
            @ApiParam(value = "学生卡号", required = false) @RequestParam(name = "cardNo", required = false) String cardNo,
            @ApiParam(value = "性别", required = false) @RequestParam(name = "sex", required = false) String sex,
            @ApiParam(value = "登录token", required = false) @RequestParam(name = "token", required = false) String token,
            HttpServletResponse response) {
        log.info("***********StudentManageController.exportStudentInfoExcel******...orgId:{},gradeId:{},classId:{},name:{},mobile:{},cardNo:{},sex:{}", orgId, gradeId, classId, name, mobile, cardNo, sex);

        UserDto userDto = getUserByLogin(token);
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        if (null == orgId) {
            return new ResultDTO<>(ErrorCode.PARAM_MISSING);
        }

        try {
            HashMap<String, Object> params = new HashMap<>(3);
            if (orgId != null) {
                params.put("orgId", orgId);
            }
            if (gradeId != null) {
                params.put("gradeId", gradeId);
            }
            if (classId != null) {
                params.put("classId", classId);
            }
            if (!StringUtil.isNullOrBlank(name)) {
                params.put("name", name);
            }
            if (!StringUtil.isNullOrBlank(mobile)) {
                params.put("mobile", mobile);
            }
            if (!StringUtil.isNullOrBlank(sex)) {
                params.put("sex", sex);
            }
            if (!StringUtil.isNullOrBlank(cardNo)) {
                params.put("cardNo", cardNo);
            }
            List<String> headers = new ArrayList<>();
            headers.add("学校名称");
            headers.add("学生姓名");
            headers.add("班级");
            headers.add("学号");
            headers.add("手机号");
            headers.add("学生卡号");
            headers.add("人脸照片");
            headers.add("人脸录入/修改时间");
            String[] tempArray={};

            List<Object[]> dataList = studentService.exportStudentInfoExcel(params);
            if(org.apache.commons.collections.CollectionUtils.isEmpty(dataList)){
                return  new ResultDTO<>(ErrorCode.NOT_DATA);
            }

            String fileName = "学生" + TimeUtil.toStringYYYY_MM_DD(new Date())+ "导出";
            ExcelUtil.exportAttendExcel("学生名单", fileName, headers.toArray(tempArray), dataList, response);
            return null;
        } catch (Exception e) {
            log.error("***********StudentManageController.exportStudentInfoExcel******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "调班")
    @RequestMapping(value = "/changeClassForStudent", method = RequestMethod.POST)
    public ResultDTO changeClassForStudent(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @RequestBody StudentChangeClassVo studentChangeClassVo)
    {
        log.info("***********StudentManageController.changeClassForStudent******...studentChangeClassVo:{}", studentChangeClassVo);

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        try {
            Long orgId = studentChangeClassVo.getOrgId();
            List<StudentChangeClassUserVo> studentChangeClassUserList = studentChangeClassVo.getStudentChangeClassUserList();
            for(StudentChangeClassUserVo studentChangeClassUserVo : studentChangeClassUserList) {
                log.info("***********StudentManageController.changeClassForStudent******...orgId:{},classId:{},userList:{}", orgId, studentChangeClassUserVo.getClassId(), studentChangeClassUserVo.getUserList());
                ThreadPoolUtil.addPoolTask(new ChangeClassTask(ChangeClassOperateTypeEnum.CHANGE_CLASS_TO_STUDENT_PERSON.getCode(), studentService,null, orgId, null, studentChangeClassUserVo.getClassId(), studentChangeClassUserVo.getUserList(), userDto.getName()));
            }
        }
        catch (Exception e) {
            log.error("***********StudentManageController.changeClassForStudent******", e);
            return new ResultDTO<>(false);
        }

        return new ResultDTO<>(true);
    }

    @ApiOperation(value = "查询map分组")
    @RequestMapping(value = "/getMap", method = RequestMethod.POST)
    public ResultDTO getMap(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion") String apiVersion,
            @ApiParam(value = "学校ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId
    )
    {

        UserDto userDto = getUserByLogin();
        if (userDto == null) {
            return new ResultDTO<>(ErrorCode.USER_NOT_EXIST);
        }

        try {
            HashMap<String, Object> param = new HashMap<>();
            param.put("orgId",orgId);
            // param.put("createTime",  new Date( System.currentTimeMillis() - 100000));
            List<Family> familyList = familyService.getListByMapParams(param);

            //IM每个班级进行分组
            if(CollectionUtils.isNotEmpty(familyList)){
                Map<Long, List<Family>> collect = familyList.stream().collect(Collectors.groupingBy(family -> family.getClassId()));
                for (Map.Entry<Long, List<Family>> groupFamilyList : collect.entrySet()) {
                    List<FamilyInfoDto> familyInfoDtoList = BeanUtil.copyPropertiesList(groupFamilyList.getValue(), FamilyInfoDto.class);
                    log.info("----------家长----------{}",familyInfoDtoList);
                }
            }
        }
        catch (Exception e) {
            log.error("***********StudentManageController.getMap******", e);
            return new ResultDTO<>(false);
        }

        return new ResultDTO<>(true);
    }

}
